package utils;

import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.config.ConfigureBuilder;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ooxml.POIXMLDocument;
import org.apache.poi.xwpf.usermodel.*;
import org.ddr.poi.html.HtmlRenderPolicy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * docx文档替换工具
 */
public class WordDocxReplaceUtils {
    private static final Logger log = LoggerFactory.getLogger(WordDocxReplaceUtils.class);

    /**
     * docx文档替换 (poi-tl)
     * @param templateFilePath 模板路径
     * @param outFilePath 输出路径
     * @param parMap 替换参数 替换参数 (key: {{xxx}}: 文本/ {{@xxxx}}: 图片)
     */
    public static void docxPoiReplace(String templateFilePath, String outFilePath, HashMap<String, Object> parMap){
        if (!new File(templateFilePath).exists()){
            log.error("替换文件失败，文件不存在");
            return;
        }

        ConfigureBuilder builder = Configure.builder();

        /** 模板关键配置 ${data.xxx} */
        builder.buildGramer("${data.", "}");

        /** html插件相关字段 */
        builder.bind("fjcqkzs", new HtmlRenderPolicy());
        builder.bind("jczj", new HtmlRenderPolicy());
//        builder.bind("fjcqxxm", new HtmlRenderPolicy());

        WordDocxReplaceUtils.docxConfigureReplace(templateFilePath, outFilePath, builder.build(), parMap);
    }

    /**
     * docx文档替换 (poi-tl)
     * @param templateFilePath 模板路径
     * @param outFilePath 输出路径
     * @param parMap 替换参数 替换参数 (key: {{xxx}}: 文本/ {{@xxxx}}: 图片)
     */
    public static boolean docxReplaceFlag(String templateFilePath, String outFilePath, HashMap<String, Object> parMap){
        if (!new File(templateFilePath).exists()){
            log.error("替换文件失败，文件不存在");
            return false;
        }

        XWPFTemplate template = XWPFTemplate.compile(new File(templateFilePath)).render(parMap);
        // 将完成数据渲染的文档写出
        try {
            template.writeToFile(outFilePath);
            template.close();

            return true;
        } catch (FileNotFoundException e) {
            log.error("替换文件失败【FileNotFoundException】->: {}", e.getMessage());
            return false;
        }catch (IOException e){
            log.error("替换文件失败【IOException】->: {}", e.getMessage());

            return false;
        }
    }

    /**
     * docx文档替换 (poi-tl)
     * @param templateFilePath 模板路径
     * @param outFilePath 输出路径
     * @param parMap 替换参数 替换参数 (key: {{xxx}}: 文本/ {{@xxxx}}: 图片)
     */
    public static void docxConfigureReplace(String templateFilePath, String outFilePath, Configure configure, HashMap<String, Object> parMap){
        if (!new File(templateFilePath).exists()){
            log.error("替换文件失败，文件不存在");
            return;
        }

        XWPFTemplate template = XWPFTemplate.compile(new File(templateFilePath), configure).render(parMap);
        // 将完成数据渲染的文档写出
        try {
            template.writeToFile(outFilePath);
            template.close();
        } catch (FileNotFoundException e) {
            log.error("替换文件失败【FileNotFoundException】->: {}", e.getMessage());
        }catch (IOException e){
            log.error("替换文件失败【IOException】->: {}", e.getMessage());
        }
    }

    /**
     * docx文档替换 (apache poi)
     * @param templateFilePath 模板路径
     * @param outFilePath 输出路径
     * @param map 替换参数 (key: ${data.xxx})
     */
    public static void docxReplace(String templateFilePath,String outFilePath, Map<String, String> map){
        File file = new File(templateFilePath);
        if (!file.exists()){
            log.error("替换文件失败，文件不存在");
            return;
        }

        try {
            XWPFDocument document = new XWPFDocument(POIXMLDocument.openPackage(templateFilePath));
            // 替换段落中的指定文字
            Iterator<XWPFParagraph> itPara = document.getParagraphsIterator();

            while (itPara.hasNext()) {
                XWPFParagraph paragraph = itPara.next();
                List<XWPFRun> runs = paragraph.getRuns();
                for (int i = 0; i < runs.size(); i++) {
                    String oneparaString = runs.get(i).getText(runs.get(i).getTextPosition());
                    if (oneparaString != null) {
                        for (Map.Entry<String, String> entry : map.entrySet()) {
                            oneparaString = oneparaString.replace(entry.getKey(), entry.getValue());
                        }
                        runs.get(i).setText(oneparaString, 0);
                    }
                }
            }

            /**
             * 替换表格中的指定文字
             */
            Iterator<XWPFTable> itTable = document.getTablesIterator();
            while (itTable.hasNext()) {
                XWPFTable table = (XWPFTable) itTable.next();
                int count = table.getNumberOfRows();
                for (int i = 0; i < count; i++) {
                    XWPFTableRow row = table.getRow(i);
                    List<XWPFTableCell> cells = row.getTableCells();
                    for (XWPFTableCell cell : cells) {
                        for (XWPFParagraph p : cell.getParagraphs()) {
                            for (XWPFRun r : p.getRuns()) {
                                String text = r.getText(0);
//                                    log.info("遍历该段里的所有文本-{}",text);
                                for (Map.Entry<String, String> e : map.entrySet()) {
                                    if (text != null && text.contains(e.getKey())) {
//                                            log.info("key-{}",e.getValue());
                                        text = text.replace(e.getKey(), e.getValue());
                                        r.setText(text, 0);
                                    }
                                }
                            }
                        }

                    }
                }
            }

            // 创建新文件存放新内容
            FileOutputStream outStream = new FileOutputStream(outFilePath);
            document.write(outStream);
            outStream.close();

        } catch (Exception e) {
            log.error("替换word里面的内容出错-{}", e);
        }
    }


    // 图片处理
   /* public static PictureRenderData generatePicture(String imgUrl){
        BufferedImage read = null;
        try {
            read = ImageIO.read(new File(imgUrl));
        } catch (IOException e) {
            e.printStackTrace();
        }
        int height = read.getHeight();
        int width = read.getWidth();

        PictureRenderData pictureRenderData = null;
        try {
            pictureRenderData = new PictureRenderData(width, height, ".png", new FileInputStream(imgUrl));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        return pictureRenderData;
    }*/

    // html配置渲染
    public static Configure generateHtmlConfigure(List<String> params){
        // html渲染插件
        HtmlRenderPolicy htmlRenderPolicy = new HtmlRenderPolicy();
        // 第一个案例
        // 注册html解析插件
        Configure configure = null;

        int size = params.size();

        if (size == 1){
            configure = Configure.builder()
                    .bind(params.get(0),htmlRenderPolicy)
                    .build();
        }else if (size == 2){
            configure = Configure.builder()
                    .bind(params.get(0),htmlRenderPolicy)
                    .bind(params.get(1),htmlRenderPolicy)
                    .build();
        }else if (size == 3){
            configure = Configure.builder()
                    .bind(params.get(0),htmlRenderPolicy)
                    .bind(params.get(1),htmlRenderPolicy)
                    .bind(params.get(2),htmlRenderPolicy)
                    .build();
        }else if (size == 4){
            configure = Configure.builder()
                    .bind(params.get(0),htmlRenderPolicy)
                    .bind(params.get(1),htmlRenderPolicy)
                    .bind(params.get(2),htmlRenderPolicy)
                    .bind(params.get(3),htmlRenderPolicy)
                    .build();
        }else if (size == 5){
            configure = Configure.builder()
                    .bind(params.get(0),htmlRenderPolicy)
                    .bind(params.get(1),htmlRenderPolicy)
                    .bind(params.get(2),htmlRenderPolicy)
                    .bind(params.get(3),htmlRenderPolicy)
                    .bind(params.get(4),htmlRenderPolicy)
                    .build();
        }

        return configure;
    }

    /** 查询文档中是否存在关键字（docx） */
    public static boolean searchKeywordInDocx(String filePath, String keyword) {
        try (FileInputStream fis = new FileInputStream(filePath);
             XWPFDocument document = new XWPFDocument(fis)) {

            for (XWPFParagraph para : document.getParagraphs()) {
                if (StringUtils.isNotBlank(para.getText()) && para.getText().contains(keyword)) {
                    return true;
                }
            }

            // 检查表格
            for (XWPFTable table : document.getTables()) {
                for (XWPFTableRow row : table.getRows()) {
                    for (XWPFTableCell cell : row.getTableCells()) {
                        // 注意：这里只检查了单元格的文本，可能还需要检查单元格中的其他元素（如段落）
                        if (StringUtils.isNotBlank(cell.getText()) && cell.getText().contains(keyword)) {
                            return true;
                        }

                        // 如果单元格包含更复杂的结构（如段落），你可能需要遍历这些结构
                         for (XWPFParagraph para : cell.getParagraphs()) {
                             if (StringUtils.isNotBlank(para.getText()) && para.getText().contains(keyword)) {
                                 return true;
                             }
                         }
                    }
                }
            }

            return false;
        } catch (IOException e) {
            log.error("文档查找关键字-失败：{}", e.getMessage());
            return false;
        }
    }
}
